
#include <cstdio>
#include <BMap>
#include <BSpring>
#include <BSpacer>
#include <BApplication>

#include "ReadWrite_step.h"

ReadWrite_step::ReadWrite_step()
{
	_author = "zym";
	_version = "1.0";
	_description = "This is BWE Plugin for reading *.jpg image file, writen width libjpeg, thank a lot !";
}
ReadWrite_step::~ReadWrite_step()
{

}

void ReadWrite_step::setOptions(const BString& options)
{
	_options = options;
}
const BString& ReadWrite_step::options() const
{
	return _options;
}

const BString& ReadWrite_step::author() const
{
	return _author;
}
const BString& ReadWrite_step::version() const
{
	return _version;
}
const BString& ReadWrite_step::description() const
{
	return _description;
}
const BString& ReadWrite_step::message() const
{
	return _message;
}

inline bool readItem(const BFile& file, BString& text)
{
	text.reset();
	char code = 0;
	while (file.read(code))
	{
		text.append(code);
		if (code == ';')
			break;
	}
	return !text.empty();
}

BObject* ReadWrite_step::load(const BString& fileName)
{
	_pointMap.clear();
	_vertexPointMap.clear();
	_colorMap.clear();
	_directionMap.clear();
	_edgeLoopMap.clear();

	BFile file(fileName);
	if (!file.open(IO_Read))
	{
		printf("STEP error -- read failed : %s\n", fileName.cstr());
		return 0;
	}

	BString text;
	if (!readItem(file, text))
	{
		printf("read step error : read first line text failed.\n");
		return 0;
	}

	text.trimmed();
	if (text != "ISO-10303-21;")
	{
		printf("read step error : format standar %s is not suported.\n", text.cstr());
		return 0;
	}

	while (readItem(file, text))
	{
		text.trimmed();
		if (text == "HEADER;")
		{
			if (false == readHeader(file))
				break;
			continue;
		}
		if (text == "DATA;")
		{
			if (false == readData(file))
				break;
			continue;
		}
		if (text == "END-ISO-10303-21;")
			break;
	}

	BGeometry* geometry = new BGeometry();

	BVectorArray* vertices = new BVectorArray();
	for (auto it = _pointMap.begin(); it.valid(); it++)
	{
		it->index = vertices->size();
		vertices->append(it->point);
	}
	geometry->setVertices(vertices);

	if (_edgeLoopMap.size())
	{
		BIntArray* lineIndices = new BIntArray();
		BIntArray* trigIndices = new BIntArray();
		BIntArray* quadIndices = new BIntArray();
		for (auto it = _edgeLoopMap.begin(); it.valid(); it++)
		{
			const BIntArray& edgeloop = *it;
			if (edgeloop.size() == 2)
			{
				int oriEdge0 = edgeloop[0];
				int oriEdge1 = edgeloop[1];

				OrientedEdge& orientedEdge0 = _orientedEdgeMap(oriEdge0);
				OrientedEdge& orientedEdge1 = _orientedEdgeMap(oriEdge1);

				int edge0 = _orientedEdgeMap(edgeloop[0]).edge;
				int edge1 = _orientedEdgeMap(edgeloop[1]).edge;

				EdgeCurve edgeCurve0 = _edgeCurveMap(edge0);
				EdgeCurve edgeCurve1 = _edgeCurveMap(edge1);

				edgeCurve0.orient(orientedEdge0.symb);
				edgeCurve1.orient(orientedEdge1.symb);

				int pnum0 = _vertexPointMap(edgeCurve0.vnum0);
				int pnum1 = _vertexPointMap(edgeCurve1.vnum0);

				int index0 = _pointMap[pnum0].index;
				int index1 = _pointMap[pnum1].index;

				lineIndices->append(index0);
				lineIndices->append(index1);
				continue;
			}
			if (edgeloop.size() == 3)
			{
				int oriEdge0 = edgeloop[0];
				int oriEdge1 = edgeloop[1];
				int oriEdge2 = edgeloop[2];

				OrientedEdge& orientedEdge0 = _orientedEdgeMap(oriEdge0);
				OrientedEdge& orientedEdge1 = _orientedEdgeMap(oriEdge1);
				OrientedEdge& orientedEdge2 = _orientedEdgeMap(oriEdge2);

				int edge0 = _orientedEdgeMap(edgeloop[0]).edge;
				int edge1 = _orientedEdgeMap(edgeloop[1]).edge;
				int edge2 = _orientedEdgeMap(edgeloop[2]).edge;

				EdgeCurve edgeCurve0 = _edgeCurveMap(edge0);
				EdgeCurve edgeCurve1 = _edgeCurveMap(edge1);
				EdgeCurve edgeCurve2 = _edgeCurveMap(edge2);

				edgeCurve0.orient(orientedEdge0.symb);
				edgeCurve1.orient(orientedEdge1.symb);
				edgeCurve2.orient(orientedEdge2.symb);

				int pnum0 = _vertexPointMap(edgeCurve0.vnum0);
				int pnum1 = _vertexPointMap(edgeCurve1.vnum0);
				int pnum2 = _vertexPointMap(edgeCurve2.vnum0);

				int index0 = _pointMap[pnum0].index;
				int index1 = _pointMap[pnum1].index;
				int index2 = _pointMap[pnum2].index;

				quadIndices->append(index0);
				quadIndices->append(index1);
				quadIndices->append(index2);
				continue;
			}
			if (edgeloop.size() == 4)
			{
				int oriEdge0 = edgeloop[0];
				int oriEdge1 = edgeloop[1];
				int oriEdge2 = edgeloop[2];
				int oriEdge3 = edgeloop[3];

				OrientedEdge& orientedEdge0 = _orientedEdgeMap(oriEdge0);
				OrientedEdge& orientedEdge1 = _orientedEdgeMap(oriEdge1);
				OrientedEdge& orientedEdge2 = _orientedEdgeMap(oriEdge2);
				OrientedEdge& orientedEdge3 = _orientedEdgeMap(oriEdge3);

				int edge0 = _orientedEdgeMap(edgeloop[0]).edge;
				int edge1 = _orientedEdgeMap(edgeloop[1]).edge;
				int edge2 = _orientedEdgeMap(edgeloop[2]).edge;
				int edge3 = _orientedEdgeMap(edgeloop[3]).edge;

				EdgeCurve edgeCurve0 = _edgeCurveMap(edge0);
				EdgeCurve edgeCurve1 = _edgeCurveMap(edge1);
				EdgeCurve edgeCurve2 = _edgeCurveMap(edge2);
				EdgeCurve edgeCurve3 = _edgeCurveMap(edge3);

				edgeCurve0.orient(orientedEdge0.symb);
				edgeCurve1.orient(orientedEdge1.symb);
				edgeCurve2.orient(orientedEdge2.symb);
				edgeCurve3.orient(orientedEdge3.symb);

				int pnum0 = _vertexPointMap(edgeCurve0.vnum0);
				int pnum1 = _vertexPointMap(edgeCurve1.vnum0);
				int pnum2 = _vertexPointMap(edgeCurve2.vnum0);
				int pnum3 = _vertexPointMap(edgeCurve3.vnum0);

				int index0 = _pointMap[pnum0].index;
				int index1 = _pointMap[pnum1].index;
				int index2 = _pointMap[pnum2].index;
				int index3 = _pointMap[pnum3].index;

				quadIndices->append(index0);
				quadIndices->append(index1);
				quadIndices->append(index2);
				quadIndices->append(index3);
				continue;
			}
			if (edgeloop.size() > 4)
			{
				BIntArray* polyIndices = new BIntArray();
				for (int i = 0; i < edgeloop.size(); i++)
				{
					int oriEdge = edgeloop[i];
					OrientedEdge& orientedEdge = _orientedEdgeMap(oriEdge);
					int edge = _orientedEdgeMap(oriEdge).edge;
					EdgeCurve edgeCurve = _edgeCurveMap(edge);
					edgeCurve.orient(orientedEdge.symb);
					int pnum = _vertexPointMap(edgeCurve.vnum0);
					int index = _pointMap[pnum].index;
					polyIndices->append(index);
				}
				geometry->addElement(Primitive_Polygon, polyIndices);
				continue;
			}
		}
		geometry->addElement(Primitive_Lines, lineIndices);
		geometry->addElement(Primitive_Triangles, trigIndices);
		geometry->addElement(Primitive_Quads, quadIndices);
	}
	geometry->smooth();
	return geometry;
}
bool ReadWrite_step::load(const BString& fileName, BObject* object)
{
	if (!object)
		return false;

	BFile file(fileName);
	if (!file.open(IO_Read))
	{
		printf("STEP error -- read failed : %s\n", fileName.cstr());
		return false;
	}

	return false;
}
bool ReadWrite_step::save(const BString& fileName, const BObject* object) const
{
	if (!object)
		return false;

	BFile file(fileName);
	if (!file.open(IO_Write))
	{
		printf("STEP error -- write failed : %s\n", fileName.cstr());
		return false;
	}

	return false;
}

BObject* ReadWrite_step::read(const BBuffer& buffer)
{
	return 0;
}
bool ReadWrite_step::read(const BBuffer& buffer, BObject* object)
{
	return false;
}
bool ReadWrite_step::write(BBuffer& buffer, const BObject* object) const
{
	return false;
}

bool ReadWrite_step::readHeader(const BFile& file)
{
	BString text;
	while (readItem(file, text))
	{
		text.trimmed();
		if (text.beginWith("FILE_DESCRIPTION"))
		{
			text.remove(0, 17);
			if (2 == text.split(_strlst, ','))
			{
				const BString& str0 = _strlst(0);
				const BString& str1 = _strlst(1);
			}
			continue;
		}
		if (text.beginWith("FILE_NAME"))
		{
			text.remove(0, 10);
			if (7 == text.split(_strlst, ','))
			{
				const BString& str0 = _strlst(0);
				const BString& str1 = _strlst(1);
				const BString& str2 = _strlst(2);
				const BString& str3 = _strlst(3);
				const BString& str4 = _strlst(4);
				const BString& str5 = _strlst(5);
				const BString& str6 = _strlst(6);
			}
			continue;
		}
		if (text.beginWith("FILE_SCHEMA"))
		{
			text.remove(0, 12);
			continue;
		}
		if (text == "ENDSEC;")
			return true;
	}
	return false;
}
bool ReadWrite_step::readData(const BFile& file)
{
	BString text;
	while (readItem(file, text))
	{
		text.trimmed();
		if (text == "ENDSEC;")
			return true;
		if (!text.beginWith('#'))
		{
			printf("data item not begin with '#' : %s.\n", text.cstr());
			return false;
		}
		text.remove(0);
		int number = text.toInt();
		int pos = text.find('=');
		text.truncate(pos + 1);
		text.trimmed();
		if (text.beginWith("CARTESIAN_POINT"))
		{
			text.remove(0, 16);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			text.removeHead('(');
			text.removeTail(')');
			if (3 == text.split(_strlst, ','))
			{
				PointCell& cell = _pointMap[number];
				cell.point.x() = _strlst[0].toReal();
				cell.point.y() = _strlst[1].toReal();
				cell.point.z() = _strlst[2].toReal();
				//printf("point %d : %s\n", number, text.cstr());
			}
			continue;
		}
		else if (text.beginWith("VERTEX_POINT"))
		{
			text.remove(0, 12);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			if (2 == text.split(_strlst, ','))
			{
				_strlst[0].remove('#');
				_strlst[1].remove('#');
				int normal_num = _strlst[0].toInt();
				int point_num = _strlst[1].toInt();
				_vertexPointMap[number] = point_num;
			}
			continue;
		}
		else if (text.beginWith("VECTOR"))
		{
			text.remove(0, 6);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			if (3 == text.split(_strlst, ','))
			{
				_strlst[1].remove('#');
				int direct = _strlst[1].toInt();
				_vectorDirectMap[number] = direct;
			}
			continue;
		}
		else if (text.beginWith("COLOUR_RGB"))
		{
			text.remove(0, 10);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			if (3 == text.split(_strlst, ','))
			{
				BByte r = BByte(_strlst[0].toFloat() * 255);
				BByte g = BByte(_strlst[1].toFloat() * 255);
				BByte b = BByte(_strlst[2].toFloat() * 255);
				_colorMap[number] = BColor(r, g, b);
			}
			continue;
		}
		else if (text.beginWith("ADVANCED_FACE"))
		{
			continue;
		}
		else if (text.beginWith("LINE"))
		{
			text.remove(0, 4);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			if (2 == text.split(_strlst, ','))
			{
				_strlst[0].remove('#');
				_strlst[1].remove('#');
				LineCell& line = _lineMap[number];
				line.pnum = _strlst[0].toInt();
				line.vnum = _strlst[1].toInt();
			}
			continue;
		}
		else if (text.beginWith("CIRCLE"))
		{
			text.remove(0, 6);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("DIRECTION"))
		{
			text.remove(0, 9);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			text.removeHead('(');
			text.removeTail(')');
			if (3 == text.split(_strlst, ','))
			{
				BVector vec;
				vec.x() = _strlst[0].toReal();
				vec.y() = _strlst[1].toReal();
				vec.z() = _strlst[2].toReal();
				_directionMap[number] = vec;
			}
			continue;
		}
		else if (text.beginWith("EDGE_CURVE"))
		{
			text.remove(0, 10);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			if (4 == text.split(_strlst, ','))
			{
				_strlst[0].remove('#');
				_strlst[1].remove('#');
				_strlst[2].remove('#');
				EdgeCurve& edge = _edgeCurveMap[number];
				edge.vnum0 = _strlst[0].toInt();
				edge.vnum1 = _strlst[1].toInt();
				edge.curve = _strlst[2].toInt();
				edge.symbol = _strlst[3].cstr()[1];
			}
			continue;
		}
		else if (text.beginWith("ORIENTED_EDGE"))
		{
			text.remove(0, 13);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			text.removeHead('(');
			text.removeTail(')');
			if (4 == text.split(_strlst, ','))
			{
				_strlst[0].remove('#');
				_strlst[1].remove('#');
				_strlst[2].remove('#');
				OrientedEdge& edge = _orientedEdgeMap[number];
				edge.val0 = _strlst[0].toInt();
				edge.val1 = _strlst[1].toInt();
				edge.edge = _strlst[2].toInt();
				edge.symb = _strlst[3].cstr()[1];
			}
			continue;
		}
		else if (text.beginWith("EDGE_LOOP"))
		{
			text.remove(0, 9);
			text.compact();
			text.removeHead('(');
			text.removeTail(");");
			text.remove(0, text.find(',') + 1);
			text.removeHead('(');
			text.removeTail(')');
			if (int count = text.split(_strlst, ','))
			{
				BIntArray& edgeLoop = _edgeLoopMap[number];
				edgeLoop.resize(_strlst.size());
				for (int i = 0; i < _strlst.size(); i++)
				{
					_strlst[i].remove('#');
					edgeLoop[i] = _strlst[i].toInt();
				}
			}
			continue;
		}
		else if (text.beginWith("SURFACE_STYLE_USAGE"))
		{
			continue;
		}
		else if (text.beginWith("PRESENTATION_LAYER_ASSIGNMENT"))
		{
			continue;
		}
		else if (text.beginWith("FACE_OUTER_BOUND"))
		{
			continue;
		}
		else if (text.beginWith("AXIS2_PLACEMENT_3D"))
		{
			continue;
		}
		else if (text.beginWith("SHAPE_REPRESENTATION_RELATIONSHIP"))
		{
			continue;
		}
		else if (text.beginWith("SURFACE_STYLE_FILL_AREA"))
		{
			continue;
		}
		else if (text.beginWith("STYLED_ITEM"))
		{
			continue;
		}
		else if (text.beginWith("FILL_AREA_STYLE_COLOUR"))
		{
			text.remove(0, 22);
			text.compact();
			text.remove('(');
			text -= ");";
			if (2 == text.split(_strlst, ','))
			{
				int xxxxx_num = _strlst[0].toInt();
				int color_num = _strlst[1].toInt();
			}
			continue;
		}
		else if (text.beginWith("B_SPLINE_CURVE_WITH_KNOTS"))
		{
			text.remove(0, 25);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("ITEM_DEFINED_TRANSFORMATION"))
		{
			text.remove(0, 27);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("SHAPE_REPRESENTATION"))
		{
			text.remove(0, 20);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("PRESENTATION_STYLE_ASSIGNMENT"))
		{
			text.remove(0, 20);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("CLOSED_SHELL"))
		{
			text.remove(0, 12);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("UNCERTAINTY_MEASURE_WITH_UNIT"))
		{
			text.remove(0, 29);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("CONICAL_SURFACE"))
		{
			text.remove(0, 15);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		else if (text.beginWith("CYLINDRICAL_SURFACE"))
		{
			text.remove(0, 19);
			text.compact();
			text.remove('(');
			text -= ");";
			continue;
		}
		puts(text.cstr());
	}
	return false;
}

